package com.lambkit.db;

import cn.hutool.core.util.ClassUtil;
import com.lambkit.core.Lambkit;
import com.lambkit.db.dialect.IDialect;
import com.lambkit.db.sql.Example;

import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.concurrent.Future;

public abstract class AbstractDaoService<M extends RowModel<M>> implements IDaoService<M>, IDbOpt<M, PageData<M>> {

    @Override
    public IDialect getDialect() {
        return dao().getDialect();
    }

    @Override
    public void setDialect(IDialect dialect) {
        dao().setDialect(dialect);
    }

    @Override
    public String getTableName() {
        M m = Lambkit.get(getModelClass());
        return m != null ? m.tableName() : null;
    }

    @Override
    public String getPrimaryKey() {
        M m = Lambkit.get(getModelClass());
        return m != null ? m.primaryKey() : null;
    }

    // 添加获取模型类的方法
    protected Class<M> getModelClass() {
        ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
        return (Class<M>) type.getActualTypeArguments()[0];
    }


    @Override
    public M findById(Object... idValues) {
        return dao().findById(getTableName(), getPrimaryKey(), idValues);
    }

    @Override
    public int deleteById(Object... idValues) {
        return dao().deleteById(getTableName(), getPrimaryKey(), idValues);
    }

    @Override
    public M findFirst(Example example) {
        return dao().findFirst(example);
    }

    @Override
    public List<M> find(Sql sqlPara) {
        return find(sqlPara.getSql(), sqlPara.getPara());
    }

    @Override
    public List<M> find(Example example, Integer count) {
        return dao().find(example, count);
    }

    @Override
    public List<M> find(Example example) {
        return find(example, null);
    }

    @Override
    public List<M> findAll(String tableName) {
        return find(Example.create(tableName), null);
    }

    @Override
    public PageData<M> paginate(Integer pageNumber, Integer pageSize, Sql sqlPara) {
        return dao().paginate(pageNumber, pageSize, sqlPara);
    }

    @Override
    public PageData<M> paginate(Integer pageNumber, Integer pageSize, Example example) {
        return dao().paginate(pageNumber, pageSize, example);
    }

    @Override
    public PageData<M> paginate(Sql sqlPara, Integer offset, Integer limit) {
        int pageSize = limit;
        int pageNumber = offset / pageSize + 1;
        return paginate(pageNumber, pageSize, sqlPara);
    }

    @Override
    public PageData<M> paginate(Example example, Integer offset, Integer limit) {
        int pageSize = limit;
        int pageNumber = offset / pageSize + 1;
        return paginate(pageNumber, pageSize, example);
    }

    public Long count(Sql sqlPara) {
        return dao().count(sqlPara);
    }

    @Override
    public Long count(Example example) {
        return dao().count(example);
    }

    public boolean save(M record) {
        return dao().save(record);
    }

    public boolean delete(M record) {
        return dao().delete(record);
    }

    @Override
    public int delete(Sql sqlPara) {
        return delete(sqlPara.getSql(), sqlPara.getPara());
    }

    @Override
    public int delete(Example example) {
        return dao().delete(example);
    }

    public boolean update(M record) {
        return dao().update(record);
    }

    @Override
    public int update(Sql sqlPara) {
        return update(sqlPara.getSql(), sqlPara.getPara());
    }

    public int update(String sql, Object... paras) {
        return dao().update(sql, paras);
    }

    @Override
    public int update(String sql) {
        return update(sql, new Object[] {});
    }

    @Override
    public boolean saveOrUpdate(M rowData) {
        return dao().saveOrUpdate(rowData);
    }

    public List<M> find(String sql, Object... paras) {
        return dao().find(sql, paras);
    }

    @Override
    public List<M> find(String sql) {
        return find(sql, new Object[] {});
    }

    public List<M> find(M rowData) {
        return dao().find(rowData);
    }

    @Override
    public M findFirst(String sql, Object... paras) {
        return dao().findFirst(sql, paras);
    }

    @Override
    public M findFirst(Sql sqlPara) {
        return findFirst(sqlPara.getSql(), sqlPara.getPara());
    }

    @Override
    public M findFirst(String sql) {
        return findFirst(sql, new Object[] {});
    }

    @Override
    public M findFirst(M rowData) {
        return dao().findFirst(rowData);
    }

    @Override
    public M findById(String table, String primaryKeys, Object... idValues) {
        return dao().findById(table, primaryKeys, idValues);
    }

    public int delete(String sql, Object... paras) {
        return dao().delete(sql, paras);
    }

    @Override
    public int delete(String sql) {
        return delete(sql, new Object[] {});
    }

    @Override
    public int deleteById(String table, String primaryKeys, Object... idValues) {
        return dao().deleteById(table, primaryKeys, idValues);
    }

    @Override
    public <V extends IDbOpt> boolean tx(ITxAction<V> atom) {
        return tx(null, atom);
    }

    @Override
    public <V extends IDbOpt> boolean tx(Integer transactionLevel, ITxAction<V> atom) {
        return dao().tx(transactionLevel, atom);
    }

    @Override
    public <V extends IDbOpt> Future<Boolean> txInNewThread(ITxAction<V> atom) {
        return txInNewThread(null, atom);
    }

    @Override
    public <V extends IDbOpt> Future<Boolean> txInNewThread(Integer transactionLevel, ITxAction<V> atom) {
        return dao().txInNewThread(transactionLevel, atom);
    }

    @Override
    public List<M> findByCache(String cacheName, Object key, Sql sqlPara) {
        return dao().findByCache(cacheName, key, sqlPara);
    }

    @Override
    public List<M> findByCache(String cacheName, Object key, Example example) {
        return dao().findByCache(cacheName, key, example);
    }

    @Override
    public M findFirstByCache(String cacheName, Object key, Sql sqlPara) {
        return dao().findFirstByCache(cacheName, key, sqlPara);
    }

    @Override
    public M findFirstByCache(String cacheName, Object key, Example example) {
        return dao().findFirstByCache(cacheName, key, example);
    }

    @Override
    public PageData<M> paginateByCache(String cacheName, Object key, int pageNumber, int pageSize, Sql sqlPara) {
        return dao().paginateByCache(cacheName, key, pageNumber, pageSize, sqlPara);
    }

    @Override
    public PageData<M> paginateByCache(String cacheName, Object key, int pageNumber, int pageSize, Example example) {
        return dao().paginateByCache(cacheName, key, pageNumber, pageSize, example);
    }

    @Override
    public int[] batch(String sql, Object[][] paras, int batchSize) {
        return dao().batch(sql, paras, batchSize);
    }

    @Override
    public int[] batch(List<String> sqlList, int batchSize) {
        return dao().batch(sqlList, batchSize);
    }

    @Override
    public int[] batchSave(List<M> recordList, int batchSize) {
        return dao().batchSave(recordList, batchSize);
    }

    @Override
    public int[] batchUpdate(List<M> recordList, int batchSize) {
        return dao().batchUpdate(recordList, batchSize);
    }
}
